home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 7 / FM Towns Free Software Collection 7.iso / ms_dos / thmake / thmake.c < prev    next >
C/C++ Source or Header  |  1993-11-30  |  21KB  |  1,026 lines

  1.  
  2. /*
  3.     “THmake”MAKEユーティリティー
  4.  
  5.         By 五味
  6.  
  7. */
  8.  
  9.  
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <ctype.h>
  14. #include <time.h>
  15.  
  16. #define    TRUE    -1
  17. #define    FALSE    0
  18.  
  19. #define    SUCCESS    0
  20. #define    FAILED    -1
  21. #define    NONE    0
  22. #define    FULL    (void *)0xffff
  23.  
  24. #define    LBUFSIZE    4096
  25.     /* 行バッファの最大容量    */
  26.  
  27.  
  28. char    *helpmes=    " 'THmake' MAKE utility v1.1b\n"
  29.             " (c) H.Gomi  1993/08/12\n"
  30.             "\n"
  31.             " [usage] THmake [-?hH][-d][-e][-m][-i]\n"
  32.             "\t\t[-v][-c][-Dname macro][-t][-p]\n"
  33.             "\t\t[-f makefilename] [[making target]...]\n";
  34.  
  35. struct    defdflt    {
  36.     char    *src;
  37.     char    *dst;
  38.     struct defdflt    *sp;    /* 次へのポインタ    */
  39.     struct def2way    *spn;    /* 子項目への子ポインタ    */
  40.     };
  41.  
  42. struct    def4way    {
  43.     struct def2way    *src;
  44.     struct def2way    *dst;
  45.     struct def4way    *sp;    /* 次へのポインタ    */
  46.     struct def2way    *spn;    /* 子項目への子ポインタ    */
  47.     };
  48.  
  49. struct    def2way    {
  50.     char    *cen;        /* 文            */
  51.     struct    def2way    *sp;    /* 次へのポインタ    */
  52.     };
  53.  
  54. struct    defmac    {
  55.     char    *src;        /* 変数名        */
  56.     char    *dst;        /* 内容            */
  57.     struct    defmac    *sp;    /* 次へのポインタ    */
  58.     };
  59.  
  60.  
  61.     struct defmac    *defm,*tdefm,*mdefm;    /* 変数定義    */
  62.  
  63.     struct defdflt    *defw,*tdefw,*mdefw;    /* 省略文法条件    */
  64.     struct def2way    *defs,*tdefs,*mdefs;    /* 省略文法命令    */
  65.  
  66.     struct def4way    *defd,*tdefd,*mdefd;    /* 制作条件    */
  67.     struct def2way    *defb,*tdefb;
  68.     struct def2way    *defa,*tdefa;
  69.     struct def2way    *defc,*tdefc,*mdefc;    /* 制作命令    */
  70.  
  71.     struct def4way    *cho;            /* 重複チェック    */
  72.  
  73.  
  74.     FILE        *fp;
  75.     char        linebuf[LBUFSIZE];    /* 行バッファ        */
  76.     char        tbuf[LBUFSIZE];        /* バッファ予備        */
  77.     char        *mfname="makefile";    /* メイクファイルの名前    */
  78.     char        *outline="make.i";    /* コマンドライン書出    */
  79.     char        *highest=NULL;        /* 最上級オブジェクト    */
  80.     int        high=TRUE;        /* ターゲット存在するか    */
  81.     time_t        st[2],dt[2],nt[2];    /* 秒数バッファ        */
  82.     char        pc[]={ ' ','\0' };    /* 間隔記号        */
  83.     char        fc[]={ 0xff,'\0' };    /* 展開用補助記号    */
  84.  
  85.     unsigned int    line=1;            /* 行番号        */
  86.  
  87.     int        doImake;        /* メイク処理をするか    */
  88.     int        doIexec=TRUE;        /* コマンド実行するか    */
  89.     int        doIdisp=TRUE;        /* コマンド表示するか    */
  90.     int        doIdval=FALSE;        /* マクロ内容の表示    */
  91.     int        doIdpro=FALSE;        /* プロセス表示するか    */
  92.     int        doIlist=FALSE;        /* 依存関係表示するか    */
  93.     int        doIigno=FALSE;        /* 返値を無視するか    */
  94.     int        doIcomm=FALSE;        /* インタプリタを通すか    */
  95.     int        doIolyt=FALSE;        /* タッチのみか        */
  96.     int        lldisp,llcomm,lligno;    /* ローカル属性        */
  97.  
  98.  
  99. /*
  100.     下級関数群
  101.  
  102.  
  103. */
  104.  
  105. char *elloc(size_t size)    /* メモリオーバーアボート付「malloc」    */
  106. {
  107.     char    *s;
  108.  
  109.     if( (s=(char *)malloc(size))==NULL ) {
  110.         printf(" %s %d: out of memory.\n",mfname,line);
  111.         exit(2);
  112.     } else
  113.         return s;
  114. }
  115.  
  116. char *estrdup(char *p)        /* メモリオーバーアボート付「strdup」    */
  117. {
  118.     if( (p=strdup(p)) )
  119.         return p;
  120.     else {
  121.         printf(" %s %d: out of memory.\n",mfname,line);
  122.         exit(2);
  123.     }
  124. }
  125.  
  126. /*
  127.     フィルタ関数群
  128.  
  129.  
  130. */
  131.  
  132. void rplmac(char str[])
  133. {
  134.     unsigned int    srcp,dstp,lp,ef;
  135.  
  136.     strcpy(tbuf,str);
  137.     for( srcp=dstp=0 ; tbuf[srcp]!='\0' ; ) {
  138.         if( tbuf[srcp]=='$' && tbuf[srcp+1]=='(' ) {
  139.  
  140.             for( srcp+=2,lp=srcp ; tbuf[srcp]!=')' ; srcp++ ) {
  141.                 if( tbuf[srcp]=='\0' ) {
  142.         printf(" %s %d: マクロ展開の表記が異常です.",mfname,line);
  143.                     exit(1);
  144.                 }
  145.             }
  146.  
  147.             tbuf[srcp++]='\0';
  148.  
  149.         for( tdefm=mdefm,ef=FALSE ; tdefm!=NULL ; tdefm=tdefm->sp ) {
  150.                 if( strcmp(tdefm->src,&tbuf[lp])==0 ) {
  151.                     strcpy(&str[dstp],tdefm->dst);
  152.                     dstp+=strlen(tdefm->dst);
  153.                     ef=TRUE;
  154.                     break;
  155.                 }
  156.             }
  157.  
  158.             if( ef==FALSE )
  159.             printf(" %s %d: warning: macro'%s' undefined.");
  160.  
  161.         } else {
  162.             str[dstp++]=tbuf[srcp++];
  163.         }
  164.  
  165.     }
  166.  
  167.     str[dstp]='\0';
  168.  
  169. }
  170.  
  171. void execpp(char *str,struct def4way *stp)
  172. {
  173.     int    ll;
  174.     struct def2way    *tsp;
  175.     char    *p,*q;
  176.  
  177.     for( strcpy(linebuf,str) ; (p=strchr(linebuf,'$')) ; ) {
  178.         *p='\0';
  179.         strcpy(tbuf,linebuf);
  180.         switch(*(p+1)) {
  181.         case':':
  182.             pc[0]=*(p+2);
  183.             strcat(tbuf,p+3);
  184.             break;
  185.         case'<':
  186.             strcat(tbuf,stp->src->cen);
  187.             strcat(tbuf,p+2);
  188.             break;
  189.         case'@':
  190.             strcat(tbuf,stp->dst->cen);
  191.             strcat(tbuf,p+2);
  192.             break;
  193.         case'#':
  194.             for( tsp=stp->src,ll=0 ; tsp!=NULL ; tsp=tsp->sp ) {
  195.                 if( (ll++) )
  196.                     strcat(tbuf,pc);
  197.                 strcat(tbuf,tsp->cen);
  198.             }
  199.             strcat(tbuf,p+2);
  200.             break;
  201.         case'?':
  202.             for( tsp=stp->src,ll=0 ; tsp!=NULL ; tsp=tsp->sp ) {
  203.                 gftime(tsp->cen,st);
  204.                 if( st[0]>nt[0] ) {
  205.                     if( (ll++) )
  206.                         strcat(tbuf,pc);
  207.                     strcat(tbuf,tsp->cen);
  208.                 }
  209.             }
  210.             strcat(tbuf,p+2);
  211.             break;
  212.         case'{':
  213.             strcat(tbuf,fc);
  214.             strcat(tbuf,p+1);
  215.             break;
  216.         default:
  217.             printf(" %s: マクロ表記が異常です.\n",mfname);
  218.             exit(1);
  219.         }
  220.  
  221.         strcpy(linebuf,tbuf);
  222.     }
  223.  
  224.  
  225.     for( ; (p=strchr(linebuf,0xff))!=NULL ; ) {
  226.         *p='\0';
  227.         strcpy(tbuf,linebuf);
  228.         strcat(tbuf,outline);
  229.         if( (q=strchr(p+2,'}'))==NULL ) {
  230.         printf(" %s: '${...}'による展開の表記が不完全です.\n",mfname);
  231.             exit(1);
  232.             }
  233.         if( (fp=fopen(outline,"w"))==NULL ) {
  234. printf(" %s: accident: コマンドライン展開用のファイルが作れません.\n",mfname);
  235.             exit(2);
  236.             }
  237.         *q='\0';
  238.         fputs(p+2,fp);
  239.         fclose(fp);
  240.         strcat(tbuf,q+1);
  241.  
  242.         strcpy(linebuf,tbuf);
  243.     }
  244. }
  245.  
  246. char *linepp(char str[])    /* 行の前処理(返値はlinebuf[...])    */
  247. {
  248.     unsigned int    lp;            /* 行ポインタ    */
  249.  
  250.     if( str[0]==EOF )
  251.         return FALSE;            /* EOF調査    */
  252.     *strchr(str,'\n')='\0';            /* CR削除    */
  253.  
  254.     rplmac(str);                /* マクロ置換    */
  255.  
  256.     for( lp=0 ; str[lp]==' ' || str[lp]=='\t' ; lp++ );
  257.     if( str[lp]=='\0' )
  258.         return NULL;            /* 空行        */
  259.     if( lp>0 )
  260.         strcpy(str,&str[lp]);        /* 行詰め    */
  261.  
  262.     for( lp=strlen(str)-1 ; str[lp]==' ' || str[lp]=='\t' ; lp-- );
  263.     str[lp+1]='\0';                /* 行末詰め    */
  264.  
  265.     return str;
  266. }
  267.  
  268. char *getline(void)        /* エラーと前処理付き一行入力    */
  269. {
  270.     char    *p;
  271.     size_t    l;
  272.  
  273.     for( linebuf[0]='\0' ; (p=fgets(tbuf,LBUFSIZE,fp))!=NULL ; ) {
  274.         line++;
  275.         strcat(linebuf,tbuf);
  276.  
  277.         if( (p=strchr(linebuf,'#')) )
  278.             if( linebuf==p || *(p-1)==' ' || *(p-1)=='\t' )
  279.                 *p='\0';
  280.         if( (l=strlen(linebuf))>2 && linebuf[l-2]=='\\' &&
  281.         ( linebuf[l-3]==' ' || linebuf[l-3]=='\t' )    )
  282.             linebuf[l-2]='\0';        /* 行継続文字    */
  283.         else
  284.         if( (p=linepp(linebuf)) )
  285.             return p;
  286.     }
  287.  
  288.     if( feof(fp) )
  289.         return NULL;
  290.     else {
  291.         printf(" %s %d: accident: read failed.\n",mfname,line);
  292.         exit(3);
  293.     }
  294.  
  295. }
  296.  
  297. /*
  298.     汎用処理関数群
  299.  
  300.  
  301. */
  302.  
  303. char *getsrc(char *str)        /* 省略表記による下のファイルがあるか否か */
  304. {
  305.     char        *ttbuf;
  306.     struct defdflt    *ttdefw;    /* tdefw 暗黙使用の為のテンポラリ */
  307.  
  308.     if( strchr(str,'.')==NULL )
  309.         return(NONE);
  310.     for( tdefw=mdefw->sp,ttbuf=NULL ; tdefw!=NULL ; tdefw=tdefw->sp )
  311.         if( stricmp(tdefw->dst,strchr(str,'.')+1)==0 ) {
  312.             strcpy(tbuf,str);
  313.             strcpy(strchr(tbuf,'.')+1,tdefw->src);
  314.             if( access(tbuf,0)==0 )        /* 存在するか?    */
  315.                 return(estrdup(tbuf));
  316.             else if( ttbuf==NULL ) {
  317.                 ttbuf=tbuf;
  318.                 ttdefw=tdefw;
  319.             }
  320.         }
  321.  
  322.     if( ttbuf ) {
  323.         tdefw=ttdefw;
  324.         return(estrdup(ttbuf));
  325.     }else
  326.         return(NONE);
  327. }
  328.  
  329. void setbase(void)        /* 依存関係の複合構造体のベースを作る    */
  330. {
  331.  
  332.     tdefd=(struct def4way *)elloc(sizeof(struct def4way));
  333.     defd->sp=tdefd;
  334.     defd=tdefd;
  335.     defd->sp =NULL;        /* メイク条件の保存    */
  336.     defd->spn=NULL;
  337.  
  338.     defb=(struct def2way *)elloc(sizeof(struct def2way));
  339.     defb->sp =NULL;
  340.     defb->cen="\0";
  341.     defd->src=defb;
  342.  
  343.     defa=(struct def2way *)elloc(sizeof(struct def2way));
  344.     defa->sp =NULL;
  345.     defa->cen="\0";
  346.     defd->dst=defa;
  347. }
  348.  
  349. /*
  350.     データ処理部
  351.  
  352.  
  353. */
  354.  
  355. int making(char *str)        /* 省略規制利用のシングル    */
  356. {
  357.     char    *srcp,*dstp;
  358.  
  359.     if( (srcp=getsrc(dstp=estrdup(str))) ) {
  360.         setbase();
  361.         defd->spn=tdefw->spn;        /* tdefw 暗黙使用    */
  362.         defb->cen=srcp;
  363.         defb->sp =NULL;
  364.         defa->cen=dstp;
  365.         defa->sp =NULL;
  366.         return SUCCESS;
  367.     } else{
  368.         free(srcp);
  369.         free(dstp);
  370.         return FAILED;
  371.     }
  372.  
  373. }
  374.  
  375. void execope(char str[])        /* めいめいの方法で実行する    */
  376. {
  377.     unsigned int    ll,lp;
  378.     char        *opt[64];
  379.  
  380.     if( llcomm==TRUE ) {
  381.         if( (ll=system(str))==-1 ) {
  382.     printf(" %s : accident: loading 'COMMAND.COM' failed.\n",mfname);
  383.             exit(2);
  384.         }
  385.     } else {
  386.         strcpy(tbuf,str);
  387.         for( lp=0,ll=0 ; TRUE ; ) {
  388.             for( ; str[lp]==' ' ; lp++ );
  389.             opt[ll++]=&str[lp];
  390.             for( ; str[lp]!=' ' ; lp++ )
  391.                 if( str[lp]=='\0' )
  392.                     goto optend;
  393.             str[lp++]='\0';
  394.         }
  395.     optend:
  396.         opt[ll]=NULL;
  397.         if( *opt[0]!='\0' ) {
  398.             if( (ll=spawnvp(P_WAIT,opt[0],opt))==-1 ) {
  399.                 if( (ll=system(tbuf))==-1 ) {
  400.         printf(" %s : accident: can't exec '%s'.\n",mfname,opt[0]);
  401.                     exit(2);
  402.                 }
  403.             }
  404.         }else{
  405.             printf(" fatal: exec NULL strings.\n");
  406.             exit(3);
  407.         }
  408.     }
  409.  
  410.  
  411.     if( ll ) {
  412.         if( lligno==FALSE ) {
  413.             printf("  break.(errorlevel %d)\n",ll);
  414.             exit(ll);
  415.         } else {
  416.             printf("  ignore error.(level %d)",ll);
  417.         }
  418.     }
  419.  
  420. }
  421.  
  422. void makedo(struct def4way *stp)    /* 依存関係を処理    */
  423. {
  424.     unsigned int    ef;
  425.     struct tm    *ltime;
  426.     struct def2way    *tsp;
  427.  
  428.  
  429.     if( doIdpro==TRUE )
  430.         printf(" checking.(%s->%s)\n",stp->src->cen,stp->dst->cen);
  431.  
  432.     for( dt[0]=0,tsp=stp->src ; tsp!=NULL ; tsp=tsp->sp ) {
  433.         if( *(tsp->cen)!='\0' ) {
  434.             if( gftime(tsp->cen,st) ) {
  435.     printf(" %s: can't test time-stamp of '%s'.\n",mfname,tsp->cen);
  436.                 exit(2);
  437.             }
  438.             if( st[0]>dt[0] )
  439.                 dt[0]=st[0];
  440.         }
  441.     }            /* 最も新しいソースの時間を見る    */
  442.  
  443.  
  444.     if( dt[0]==0 ) {
  445.     printf(" %s: Don't know how to make '%s'.\n",mfname,stp->dst->cen);
  446.         exit(1);
  447.     }
  448.  
  449.  
  450.     for( nt[0]=(time_t)clock(),tsp=stp->dst ; tsp!=NULL ; tsp=tsp->sp ) {
  451.         if( *(tsp->cen)!='\0' ) {
  452.             if( gftime(tsp->cen,st)==SUCCESS ) {
  453.                 if( st[0]<nt[0] ) {
  454.                     nt[0]=st[0];
  455.                 }
  456.             } else
  457.                 nt[0]=0;    /* 無いから「最も古い」    */
  458.         }
  459.     }            /* 最も古いターゲットの時間を得る    */
  460.  
  461.  
  462.     if( doIdpro==TRUE ) {
  463.         ltime=localtime(&dt[0]);
  464.     printf("\tnewest source file time: %02d/%02d/%02d %02d:%02d:%02d\n",
  465.             ltime->tm_year,ltime->tm_mon,ltime->tm_mday,
  466.             ltime->tm_hour,ltime->tm_min,ltime->tm_sec);
  467.         if( nt[0] ) {
  468.             ltime=localtime(&nt[0]);
  469.     printf("\toldest target file time: %02d/%02d/%02d %02d:%02d:%02d\n",
  470.                 ltime->tm_year,ltime->tm_mon,ltime->tm_mday,
  471.                 ltime->tm_hour,ltime->tm_min,ltime->tm_sec);
  472.             if( nt[0]<dt[0] )
  473.                 printf("\t[up dated]\n");
  474.             else
  475.                 printf("\t[no touch]\n");
  476.         } else {
  477.             printf("\ttargets not found.\n");
  478.             printf("\t[creat]\n");
  479.         }
  480.     }        /* ファイルスタンプ比較の表示    */
  481.  
  482.  
  483.     highest=stp->dst->cen;        /* 最上級ターゲット名の書換え    */
  484.  
  485.  
  486.     if( (nt[0]<dt[0] || doIexec==FALSE) && doIolyt==FALSE ) {
  487.                     /* ソース群が新しければ処理実行    */
  488.         high=FALSE;
  489.  
  490.         for( ef=TRUE,tsp=stp->spn ; tsp!=NULL ; tsp=tsp->sp ) {
  491.             ef=FALSE;
  492.             execpp(tsp->cen,stp);
  493.  
  494.             for( lldisp=doIdisp,llcomm=doIcomm,lligno=doIigno ;;) {
  495.                     if( linebuf[0]=='@' )
  496.                         lldisp=FALSE;
  497.                 else    if( linebuf[0]=='+' )
  498.                         llcomm=TRUE;
  499.                 else    if( linebuf[0]=='-' )
  500.                         lligno=TRUE;
  501.                 else    break;
  502.  
  503.                 strcpy(linebuf,linebuf+1);
  504.             }
  505.  
  506.             if( lldisp==TRUE )
  507.                 printf("%s\n",linebuf);
  508.  
  509.             if( doIexec==TRUE )
  510.                 execope(linebuf);
  511.  
  512.         }            /* 処理行の実行        */
  513.  
  514.  
  515.         if( ef==TRUE ) {
  516.             for( tsp=stp->dst ; tsp!=NULL ; tsp=tsp->sp ) {
  517.                 if( utime(tsp->cen,NULL) ) {
  518.             printf(" %s: fatal: target'%s' not found.\n",tsp->cen);
  519.                     exit(2);
  520.                 }
  521.                 if( doIdisp==TRUE ) {
  522.                     printf(" touch '%s'.\n",tsp->cen);
  523.                 }
  524.             }        /* touch 処理    */
  525.  
  526.  
  527.  
  528.         }
  529.  
  530.     }
  531.  
  532.     stp->src=NULL;
  533.     stp->dst=NULL;
  534.     stp->spn=NULL;        /* 項目から削除    */
  535. }
  536.  
  537. struct def4way *issrc(char str[])    /* 末端か否か    */
  538. {
  539.     for( tdefd=mdefd->sp ; tdefd!=NULL ; tdefd=tdefd->sp )
  540.         for( tdefb=tdefd->dst ; tdefb!=NULL ; tdefb=tdefb->sp )
  541.             if( stricmp(str,tdefb->cen)==0 )
  542.                 return(tdefd);
  543.     return(NULL);
  544. }
  545.  
  546.  
  547. void chksrc(struct def4way *stp)    /* 関係を調べる    */
  548. {
  549.     auto struct def2way    *rdefb;
  550.     auto struct def4way    *tsp;
  551.  
  552. for( rdefb=stp->src ; rdefb!=NULL ; rdefb=rdefb->sp ) {
  553.     if( rdefb->cen ) {
  554.         if( (tsp=issrc(rdefb->cen))!=NULL ) {
  555.             if( tsp==cho ) {
  556.             printf(" %s: fatal: '%s'の作り方に矛盾がある.\n",
  557.                 mfname,stp->dst->cen);
  558.                 exit(2);
  559.             } else {
  560.                 if( cho==NULL )
  561.                     cho=tsp;
  562.             }
  563.  
  564.             chksrc(tsp);
  565.         } else {
  566.             if( making(rdefb->cen)==SUCCESS ) {
  567.                 if( doIdpro==TRUE ) {
  568.                 printf(" ('%s's source)'%s' owes '%s'.\n",
  569.         stp->dst->cen,tdefd->dst->cen,tdefd->src->cen);
  570.                 }
  571.                 chksrc(tdefd);    /* tdefd 暗黙使用    */
  572.             }
  573.  
  574.         }
  575.     }
  576. }
  577.  
  578.     cho=NULL;
  579.     makedo(stp);
  580.  
  581.     return;
  582. }
  583.  
  584.  
  585. void make(void)            /* ファイルからのメイク処理    */
  586. {
  587.     struct def4way    *rdefd;
  588.  
  589.     while(TRUE)
  590.         for( cho=NULL,rdefd=mdefd->sp ; ; rdefd=rdefd->sp ) {
  591.             if( rdefd==NULL )
  592.                 return;
  593.             if( rdefd->dst->cen ) {
  594.                 chksrc(rdefd);
  595.                 break;
  596.             }
  597.         }
  598.  
  599. }
  600.  
  601. /*
  602.     データ蓄積部
  603.  
  604.  
  605. */
  606.  
  607. struct def2way *searsrc(struct def4way *stp,int f)
  608. {
  609.     struct def2way    *tsp,*rdefs;
  610.     char        *p;
  611.  
  612. for( rdefs=NULL,tsp=stp->dst ; tsp!=NULL ; tsp=tsp->sp ) {
  613.     if( *(tsp->cen)!='\0' ) {
  614.         if( (p=getsrc(tsp->cen)) ) {
  615.             if( f++ ) {
  616.             tdefb=(struct def2way *)elloc(sizeof(struct def2way));
  617.                 defb->sp=tdefb;
  618.                 defb=tdefb;
  619.             }
  620.             defb->cen=p;
  621.             defb->sp =NULL;
  622.  
  623.             if( rdefs==NULL )
  624.                 rdefs=tdefw->spn;
  625.             else
  626.                 rdefs=FULL;
  627.  
  628.             if( doIdpro==TRUE )
  629.                 printf(" '%s' owes '%s'.\n",tsp->cen,p);
  630.  
  631.         }
  632.     }
  633. }                /* 省略規制からソース名を入手    */
  634.  
  635.     return rdefs;
  636. }
  637.  
  638. void premake(char str[])    /* メイク条件と命令の保存    */
  639. {
  640.     struct def2way    *rdef,*rdefc;
  641.     unsigned int    lp,ct,ef;
  642.     int        ll;
  643.  
  644.  
  645. if( doImake==TRUE ) {        /* ファイルから依存関係を調べる    */
  646.  
  647.     setbase();
  648.  
  649.     for( ef=TRUE,lp=0 ; ef==TRUE ; ) {
  650.  
  651.         for(       ; str[lp]==' ' || str[lp]=='\t' ; lp++ );
  652.         if( str[lp]==':' ) {
  653.             lp++;
  654.             break;
  655.         }
  656.  
  657.         for( ct=lp ; str[lp]!=' ' && str[lp]!='\t' ; lp++ )
  658.             if( str[lp]==':' ) {
  659.                 ef=FALSE;
  660.                 break;
  661.             }
  662.  
  663.         str[lp++]='\0';
  664.  
  665.         tdefa=(struct def2way *)elloc(sizeof(struct def2way));
  666.         defa->sp=tdefa;
  667.         defa=tdefa;
  668.         defa->cen=estrdup(&str[ct]);
  669.         defa->sp =NULL;
  670.  
  671.     }
  672.  
  673.  
  674.     rdef=defd->dst;
  675.     defd->dst=(defd->dst)->sp;
  676.     free(rdef);        /* ダミーの削除    */
  677.  
  678.  
  679.     rdefc=searsrc(defd,1);    /* 省略規制の該当ソース追加    */
  680.  
  681.  
  682.     for( ef=TRUE ; ef==TRUE ; ) {
  683.  
  684.         for(       ; str[lp]==' ' || str[lp]=='\t' ; lp++ );
  685.  
  686.         if( str[lp]=='\0' ) {
  687.             lp++;
  688.             break;
  689.         }
  690.  
  691.         for( ct=lp ; str[lp]!=' ' && str[lp]!='\t' ; lp++ )
  692.             if( str[lp]=='\0' ) {
  693.                 ef=FALSE;
  694.                 break;
  695.             }
  696.  
  697.         str[lp++]='\0';
  698.  
  699.         tdefb=(struct def2way *)elloc(sizeof(struct def2way));
  700.         defb->sp=tdefb;
  701.         defb=tdefb;
  702.         defb->cen=estrdup(&str[ct]);
  703.         defb->sp =NULL;
  704.     }
  705.  
  706.     rdef=defd->src;
  707.     defd->src=(defd->src)->sp;
  708.     free(rdef);        /* ダミーの削除    */
  709.  
  710.  
  711. }
  712.  
  713.  
  714.     defc=(struct def2way *)elloc(sizeof(struct def2way));
  715.     defd->spn=defc;
  716.     defc->cen="\0";
  717.     defc->sp =NULL;        /* ダミー    */
  718.  
  719.  
  720.     for( ef=TRUE ; TRUE ; ef=FALSE ) {
  721.  
  722.         if( (ll=fgetc(fp))!='\t' ) {
  723.             ungetc(ll,fp);
  724.             break;
  725.         }            /* TABだったら続ける    */
  726.  
  727.         if( getline() && doImake==TRUE ) {
  728.             tdefc=(struct def2way *)elloc(sizeof(struct def2way));
  729.             defc->sp=tdefc;
  730.             defc=tdefc;
  731.             defc->cen=estrdup(linebuf);
  732.             defc->sp =NULL;
  733.         }
  734.     }        /* 処理行の保存        */
  735.  
  736.     rdef=defd->spn;
  737.     defd->spn=(defd->spn)->sp;
  738.     free(rdef);        /* ダミーの削除    */
  739.  
  740.     if( defd->spn==NULL && rdefc!=FULL )
  741.         defd->spn=rdefc;    /* 省略時の処理方法    */
  742.  
  743. }
  744.  
  745. void defset(char *str)        /* 省略時のパターンのセット    */
  746. {
  747.     int    ll;
  748.     char    *p;
  749.  
  750.     tdefw=(struct defdflt *)elloc(sizeof(struct defdflt));
  751.     defw->sp=tdefw;
  752.     defw=tdefw;
  753.     defw->sp =NULL;            /* 省略条件の保存    */
  754.  
  755.     *(p=strchr(str,'.'))='\0';
  756.     if( stricmp(str,p+1)==0 ) {
  757.     printf(" %s %d: 省略規制の拡張子指定が違法です.\n",mfname,line);
  758.         exit(1);
  759.         }
  760.     defw->src=estrdup(str);
  761.     defw->dst=estrdup(p+1);
  762.  
  763.         defs=(struct def2way *)elloc(sizeof(struct def2way));
  764.         defw->spn=defs;
  765.         defs->cen="\0";
  766.         defs->sp =NULL;        /* 省略命令への分岐    */
  767.  
  768.     while( (ll=fgetc(fp))=='\t' )
  769.         if( getline() ) {
  770.             tdefs=(struct def2way *)elloc(sizeof(struct def2way));
  771.             defs->sp=tdefs;
  772.             defs=tdefs;
  773.             defs->cen=estrdup(linebuf);
  774.             defs->sp =NULL;
  775.         }            /* 省略命令の保存    */
  776.  
  777.     ungetc(ll,fp);
  778.  
  779.     tdefs=defw->spn;
  780.     defw->spn=defw->spn->sp;
  781.     free(tdefs);            /* ダミー削除    */
  782.  
  783.     return;
  784. }
  785.  
  786. void defmac(char *name,char *val)    /* マクロ定義    */
  787. {
  788.     for( tdefm=mdefm->sp ; tdefm!=NULL ; tdefm=tdefm->sp )
  789.         if( strcmp(tdefm->src,name)==0 ) {
  790. printf(" %s %d: warning: マクロ'%s'の再定義は無効です.\n",mfname,line,name);
  791.             return;
  792.     }
  793.  
  794.     tdefm=(struct defmac *)elloc(sizeof(struct defmac));
  795.     defm->sp=tdefm;
  796.     defm    =tdefm;
  797.     defm->sp=NULL;        /* 構造の延長    */
  798.  
  799.     defm->src=name;
  800.     defm->dst=val;
  801. }
  802.  
  803. void macset(char str[])        /* マクロ定義行の読み取り    */
  804. {
  805.     unsigned int    lp,ct,np;
  806.  
  807.     for( lp=0  ; str[lp]==' ' || str[lp]=='\t' ; lp++ );
  808.     for( ct=lp ; str[lp]!=' ' && str[lp]!='\t' && str[lp]!='=' ; lp++ );
  809.     for( np=lp ; str[lp]!='=' ; lp++ );
  810.     str[np]='\0';
  811.     for( lp++  ; str[lp]==' ' || str[lp]=='\t' ; lp++ );
  812.  
  813.     defmac(estrdup(&str[ct]),estrdup(&str[lp]));
  814. }
  815.  
  816. void commands(char str[])
  817. {
  818.     int    lp,ct;
  819.  
  820.     for( lp=1  ;
  821.         str[lp]!=' ' && str[lp]!='\t' && str[lp]!=':' && str[lp]!='\0'
  822.         ; lp++ );
  823.     for( ct=lp ;
  824.         str[lp]!=':' && str[lp]!='\0'
  825.         ; lp++ );
  826.  
  827.     if( str[lp]=='\0' ) {
  828.         printf(" %s %d: control error(without':').\n",mfname,line);
  829.         exit(1);
  830.         }
  831.  
  832.     str[ct]='\0';
  833.  
  834.         if( strchr(str,'.') )
  835.             defset(str);        /* 省略条件と命令の保存    */
  836.     else    if( !stricmp(str,"IGNORE") )
  837.             doIigno=TRUE;
  838.     else    if( !stricmp(str,"SILENT") )
  839.             doIdisp=FALSE;
  840.     else
  841.     printf(" %s %d: warning: illegal control('%s').\n",mfname,line,str);
  842.  
  843. }
  844.  
  845. void makedef(void)    /* メイク処理のメイン    */
  846. {
  847.     char    *p;
  848.  
  849.     for( ; getline()!=NULL ; line++ )
  850.         {
  851.         if( strchr(linebuf,'=') )
  852.             macset(linebuf);    /* 変数定義    */
  853.         else
  854.         if( linebuf[0]=='.' )
  855.             commands(linebuf+1);    /* コマンド発行    */
  856.         else
  857.         if( (p=strchr(linebuf,':'))!=NULL && p!=linebuf &&
  858.         ( *(p-1)==' ' || *(p-1)=='\t' )    )
  859.             premake(linebuf);    /* 条件と命令の保存    */
  860.         else
  861.             {
  862.     printf(" %s %d: syntax error.(command not found)\n",mfname,line);
  863.             exit(1);
  864.             }
  865.         }
  866. }
  867.  
  868. void initstct(void)        /* 全ての構造体の根幹を作る    */
  869. {
  870.     mdefd=(struct def4way *)elloc(sizeof(struct def4way));
  871.     defd = mdefd;
  872.     defd->sp =NULL;
  873.     defd->spn=NULL;
  874.     defd->src=NULL;
  875.     defd->dst=NULL;        /* tree構造の根幹    */
  876.  
  877.     mdefw=(struct defdflt *)elloc(sizeof(struct defdflt));
  878.     defw = mdefw;
  879.     defw->src="\0";
  880.     defw->dst="\0";
  881.     defw->spn=NULL;
  882.     defw->sp =NULL;        /* tree構造の根幹    */
  883.  
  884.     mdefm=(struct defmac *)elloc(sizeof(struct defmac));
  885.     defm = mdefm;
  886.     defm->sp =NULL;
  887.     defm->src="\0";
  888.     defm->dst="\0";        /* tree構造の根幹    */
  889.  
  890. }
  891.  
  892.  
  893. void listing(void)        /* 依存関係のリストを表示する    */
  894. {
  895.     for( tdefd=mdefd->sp ; tdefd!=NULL ; tdefd=tdefd->sp ) {
  896.         printf("---*---*---*---*---\n");
  897.         printf(" target:");
  898.         for( tdefa=tdefd->dst ; tdefa!=NULL ; tdefa=tdefa->sp )
  899.             printf(" %s",tdefa->cen);
  900.         printf("\n source:");
  901.         for( tdefb=tdefd->src ; tdefb!=NULL ; tdefb=tdefb->sp )
  902.             printf(" %s",tdefb->cen);
  903.         printf("\n");
  904.     }
  905.     printf("---* end of list\n");
  906. }
  907.  
  908.  
  909. /*
  910.     メイン
  911.  
  912.  
  913. */
  914.  
  915. int main(int argc,char *argv[])        /* メイン    */
  916. {
  917.     char        *p;
  918.     int        cm;
  919.  
  920.     initstct();        /* tree構造体の初期化    */
  921.     doImake=TRUE;
  922.  
  923.     for( cm=1 ; cm<argc ; cm++ )
  924.         {
  925.         p=argv[cm];
  926.         if( *p!='-' )
  927.             {
  928.             doImake=FALSE;
  929.             break;
  930.             }
  931.         else
  932.             switch(*(p+1))
  933.                 {
  934.             case'?':
  935.             case'h':
  936.             case'H':
  937.                 printf(helpmes);
  938.                 exit(0);
  939.             case'c':
  940.                 doIcomm=TRUE;
  941.                 break;
  942.             case'd':
  943.                 doIdisp=FALSE;
  944.                 break;
  945.             case'e':
  946.                 doIexec=FALSE;
  947.                 break;
  948.             case'm':
  949.                 doIdval=TRUE;
  950.                 break;
  951.             case'p':
  952.                 doIdpro=TRUE;
  953.                 break;
  954.             case'f':
  955.                 mfname=argv[++cm];
  956.                 break;
  957.             case'i':
  958.                 doIlist=TRUE;
  959.                 break;
  960.             case'v':
  961.                 doIigno=TRUE;
  962.                 break;
  963.             case'D':
  964.                 defmac(argv[cm]+2,argv[cm+1]);
  965.                 cm++;
  966.                 break;
  967.             case't':
  968.                 doIolyt=TRUE;
  969.                 break;
  970.             default:
  971.                 printf(" illegal option'%c'.\n",*(p+1));
  972.                 exit(2);
  973.                 }
  974.         }
  975.  
  976.  
  977.     if( (fp=fopen(mfname,"r"))==NULL )
  978.         {
  979.         printf(" fatal: '%s' not found.\n",mfname);
  980.         return(2);
  981.         }            /* file open    */
  982.  
  983.  
  984.     makedef();            /* 総合前処理    */
  985.  
  986.  
  987.     for( ; cm<argc ; cm++ ) {
  988.  
  989.         if( *argv[cm]=='-' ) {
  990.         printf(" %s: オプションがファイルの後にある.\n",mfname);
  991.             exit(1);
  992.         }
  993.  
  994.         setbase();
  995.         defa->cen=argv[cm];
  996.         if( (defd->spn=searsrc(defd,0))==NULL ) {
  997.         printf(" %s: Don't know how to make '%s'.\n",mfname,argv[cm]);
  998.             exit(1);
  999.         }
  1000.     }
  1001.  
  1002.  
  1003.     if( doIlist==TRUE )
  1004.         listing();    /* 依存関係表示    */
  1005.  
  1006.     if( doIdval==TRUE ) {
  1007.         printf("---* macro list\n");
  1008.         for( mdefm=mdefm->sp ; mdefm!=NULL ; mdefm=mdefm->sp )
  1009.             printf(" $(%s)='%s'\n",mdefm->src,mdefm->dst);
  1010.         printf("---* end of list\n");
  1011.     }            /* マクロ表示    */
  1012.  
  1013.     make();        /* 蓄積したデータを処理する    */
  1014.  
  1015.  
  1016.     if( high==TRUE )
  1017.         if( highest )
  1018.             printf(" '%s' is up to date.\n",highest);
  1019.         else
  1020.             printf(" No targets.\n");
  1021.                 /* 終了メッセージ表示    */
  1022.  
  1023.  
  1024.     return 0;        /* 正常終了    */
  1025. }
  1026.